package com.dyz.service.impl;

import com.dyz.constant.UserLoginConstant;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.security.authentication.AuthenticationServiceException;

import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import java.sql.ResultSet;
import java.sql.SQLException;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import static com.dyz.constant.UserLoginConstant.*;

@Service
public class UserDetailsServiceImpl implements UserDetailsService {
    @Resource
    private JdbcTemplate jdbcTemplate;
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
            ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            String loginType = requestAttributes.getRequest().getParameter("login_type");
            if(StringUtils.isEmpty(loginType)){
                throw new AuthenticationServiceException("登录类型不能为空");
            }
        UserDetails userDetails =null;
            try {
                //判断是否为刷新token
                String grantType = requestAttributes.getRequest().getParameter("grant_type");
                //如果是刷新token，进行纠正用户名
                if(REFRESH_TOKEN.equals(grantType.toUpperCase())){
                    username=adjustUsername(username,loginType);
                }
            if(UserLoginConstant.MEMBER_TYPE.equals(loginType)){
                //会员登录
                userDetails= loadMemberUserByUsername(username);
            }else if(UserLoginConstant.ADMIN_TYPE.equals(loginType)){
                //管理员登录
                userDetails= loadAdminUserByUsername(username);
            }else{
                throw new AuthenticationServiceException("登录类型错误"+loginType);
            }
        } catch (AuthenticationServiceException e) {
            throw new AuthenticationServiceException("用户名不存在");
        }
        return userDetails;
    }

    /**
     * 改变用户名
     * @param username
     * @param loginType
     * @return
     */
    private String adjustUsername(String username, String loginType) {
        if(UserLoginConstant.ADMIN_TYPE.equals(loginType)){
            return jdbcTemplate.queryForObject(SQL_QUERY_ADMIN_NAME_BY_ADMIN_ID, String.class, username);
            //管理员的纠正方式
        }
        if(UserLoginConstant.MEMBER_TYPE.equals(loginType)){
            //普通用户的纠正方式
            return jdbcTemplate.queryForObject(SQL_QUERY_USER_NAME_BY_USER_ID, String.class, username);
        }
        return username;
    }

    /**
     * 管理员登录
     * @param username
     * @return
     */
    private UserDetails loadAdminUserByUsername(String username) {
        try {
            return jdbcTemplate.queryForObject(UserLoginConstant.SQL_QUERY_ADMIN_BY_USERNAME, new RowMapper<User>() {
                @Override
                public User mapRow(ResultSet rs, int rowNum) throws SQLException {
                    if(rs.wasNull()){
                        throw new AuthenticationServiceException("用户名不存在");
                    }
                    String password = rs.getString("password");
                    Long id = rs.getLong("id");
                    int status = rs.getInt("status");
                   return new User(String.valueOf(id),password,status==1,true,true,true,getUserPermission(id));
                }
            },username);
        } catch (DataAccessException e) {
            throw new AuthenticationServiceException("用户名不存在");
        }
    }

    /**
     * 获取用户的权限
     * @param id
     * @return
     */
    private Set<SimpleGrantedAuthority> getUserPermission(Long id) {
        //查询用户是否为管理员
        String code = jdbcTemplate.queryForObject(SQL_QUERY_USER_IS_ADMIN, String.class, id);
        List<String> permission=null;
        if(ADMIN_CODE.equals(code)){
            //查询管理员权限
            permission = jdbcTemplate.queryForList(SQL_ALL_QUERY_PERMISSION, String.class);
        }else{
            //查询普通用户权限
            permission = jdbcTemplate.queryForList(SQL_QUERY_PERMISSION_BY_USER_ID, String.class, id);
        }
        //判断是否为空
        if(permission==null||permission.isEmpty()){
            //返回空集合
            return Collections.EMPTY_SET;
        }
        //转换为权限集合
        return permission.stream().distinct()
                .map((per)->new SimpleGrantedAuthority(per))
                .collect(Collectors.toSet());
    }
    /**
     * 普通用户登录
     * @param username
     * @return
     */
    private User loadMemberUserByUsername(String username) {
        try {
            return jdbcTemplate.queryForObject(UserLoginConstant.SQL_QUERY_USER_BY_USERNAME, new RowMapper<User>() {
                @Override
                public User mapRow(ResultSet rs, int rowNum) throws SQLException {
                    if(rs.wasNull()){
                        throw new AuthenticationServiceException("用户名不存在");
                    }
                    String password = rs.getString("password");
                    Long id = rs.getLong("id");
                    int status = rs.getInt("status");
                    return new User(String.valueOf(id),password,status==1,true,true,true, Arrays.asList(new SimpleGrantedAuthority("ROLE_USER")));
                }
            },username,username);
        } catch (DataAccessException e) {
            throw new AuthenticationServiceException("用户名不存在");
        }
    }
}
